import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';

import { NgxOlUploadOverlayRef } from '../ngx-ol-upload-overlay-ref.class';
import { ReadFilesService, Shapefile } from '../read-files.service';

@Component({
  selector: 'app-ngx-ol-upload-container',
  templateUrl: './ngx-ol-upload-container.component.html',
  styleUrls: ['./ngx-ol-upload-container.component.scss']
})
export class NgxOlUploadContainerComponent implements OnInit {

  formInstance: FormGroup;
  files: File[] = [];
  accepts: string[] = ['.zip', '.gpx', '.geojson', '.igc', '.kml', '.topojson'];
  loading: boolean = false;
  submitDisabled: boolean = true;
  alertErrorDes: string;

  constructor(
    private overlay: NgxOlUploadOverlayRef,
    private readFilesService: ReadFilesService,
    private fb: FormBuilder
  ) { }

  ngOnInit() { 
    this.formInstanceBuiler();
  }

  onFileChange(files: File[]): void {
    this.files = files || [];
    this.validate();
    this.closeAlertError();
    if(files.length === 1) {
      this.setLayerName(this.removeExtension(files[0].name));
    }
  }

  onRemoveFile(file: File): void {
    this.files = this.files.filter(_file => _file !== file);
    this.validate();
    this.closeAlertError();
  }

  onClickOkBtn(): void {
    const values = this.formInstance.value;
    this.loading = true;
    this.closeAlertError();
    if(this.attrAccept(this.files[0], ['.zip'])) {
      this.readFilesService.readShapefileAsFeatures(this.files[0])
        .subscribe(features => this.close({ ...values, features }), error => this.handleError(error));
    } else {
      this.readFilesService.readFilesAsFeatures(this.files)
        .subscribe(features => this.close({ ...values, features }), error => this.handleError(error));
    }
  }

  onClickResetBtn(): void {
    this.formInstance.reset({ layerName: '', visible: true, zoomTo: true });
    this.files = [];
    this.validate();
    this.closeAlertError();
  }

  onClickCancelBtn(): void {
    this.overlay.destroy();
  }

  private formInstanceBuiler(): void {
    this.formInstance = this.fb.group({
      layerName: ['', [Validators.required]],
      visible: [true],
      zoomTo: [true]
    });
    this.formInstance.valueChanges.subscribe(values => {
      this.closeAlertError();
    });
  }

  private removeExtension(fileName: string): string {
    const accepts = this.accepts;
    for(let i = 0; i < accepts.length; i++) {
      const validType = accepts[i].trim();
      fileName = fileName.toLowerCase().replace(new RegExp(`${validType.toLowerCase()}$`, 'g'), '');
    }
    return fileName;
  }

  private setLayerName(layerName: string): void {
    const values = this.formInstance.value;
    if(!values.layerName) {
      this.formInstance.setValue({
        ...values,
        layerName
      });
    }
  }

  private attrAccept(file: File, acceptedFiles: string | string[]): boolean {
    if (file && acceptedFiles) {
      const acceptedFilesArray = Array.isArray(acceptedFiles) ? acceptedFiles : acceptedFiles.split(',');
      const fileName = '' + file.name;
      const mimeType = '' + file.type;
      const baseMimeType = mimeType.replace(/\/.*$/, '');

      return acceptedFilesArray.some(type => {
        const validType = type.trim();
        if (validType.charAt(0) === '.') {
          return fileName.toLowerCase().indexOf(validType.toLowerCase(), fileName.toLowerCase().length - validType.toLowerCase().length) !== -1;
        } else if (/\/\*$/.test(validType)) {
          // This is something like a image/* mime type
          return baseMimeType === validType.replace(/\/.*$/, '');
        }
        return mimeType === validType;
      });
    }
    return true;
  }

  private validate(): void {
    this.submitDisabled = this.files.length === 0;
  }

  private close(result: any): void {
    this.loading = false;
    this.overlay.destroy(result);
  }

  private handleError(error): void {
    this.loading = false;
    this.alertErrorDes = '文件解析失败，请重试。';
    if(error) {
      this.alertErrorDes = error.msg || this.alertErrorDes;
    }
  }

  private closeAlertError(event?: Event): void {
    if(event) {
      event.preventDefault();
      event.stopPropagation();
    }
    this.alertErrorDes = null;
  }

}
